﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

namespace lab3
{
    /// <summary>
    /// This class manages all of the students and knows how to compute class statistics.
    /// </summary>
    /// <author>Donnie Prather gtg571m</author>
    [XmlRoot("Gradebook")]
    public class StudentList
    {
        /// Holds the list of students
        private List<Student> listOfStudents;

        public List<Student> Students
        {
            get { return listOfStudents; }
            set { listOfStudents = value; }
        }

        /// <summary>
        /// Create a new list of students
        /// </summary>
        public StudentList()
        {
            listOfStudents = new List<Student>();
        }

        /// <summary>
        /// Creates a gradebook report for the current student list.
        /// The report contains the name and average for each student
        /// and the class average and class standard deviation.
        /// </summary>
        /// <returns>A string with the gradebook report</returns>
        /// <example>
        /// GradeBook Report for CS2335
        /// Name: Bob    Average: 74.5
        /// Name: Sally  Average: 100
        /// Name: Fred   Average: 61.5
        ///
        /// Class Average = 78.6666666666667
        /// Class Deviation = 5.7
        /// </example>
        public override string ToString()
        {
            /// Create a new StringBuilder to operate on the string more efficiently
            StringBuilder sbreport = new StringBuilder();

            /// Create the report by appending lines to the StringBuilder variable
            sbreport.AppendLine("GradeBook Report for CS2335");

            /// Iterate over all of the students
            for (int i = 0; i < listOfStudents.Count; i++)
            {
                /// Add their name and average to the report
                sbreport.AppendLine(listOfStudents[i].ToString());
            }

            /// Add the class average and standard deviation
            sbreport.AppendLine("\nClass Average = " + Average());
            sbreport.AppendLine("Class Deviation = " + StandardDeviation());

            /// Convert the report created with StringBuilder back to a normal string
            /// and return it
            return sbreport.ToString();
        }

        /// <summary>
        /// Computes the average grade for the students in the list
        /// </summary>
        /// <returns>The average student grade</returns>
        public double Average()
        {
            /// Holds the sum of all of the student's averages
            double sumOfAverages = 0;
            /// The number of students in the list of students
            int numOfStudents = listOfStudents.Count;

            /// if the number of students is 0, return 0 as the average
            /// so that we don't divide by 0 later
            if (numOfStudents == 0)
            {
                return 0;
            }

            /// Iterate through all of the students
            for (int i = 0; i < numOfStudents; i++)
            {
                /// Add up all of the student averages
                sumOfAverages += listOfStudents[i].Average();
            }

            /// Return the average student grade
            return (sumOfAverages / numOfStudents);
        }
        /// <summary>
        /// Calculates the standard deviation of the grades of the students.
        /// </summary>
        /// <returns>The standard deviation</returns>
        public double StandardDeviation()
        {
            /// Calculate the average
            double classAverage = Average();
            /// Holds the variance of the student's grades
            double variance = 0;
            /// The number of students in the list of students
            int numOfStudents = listOfStudents.Count;

            /// if the number of students is 0
            if (numOfStudents == 0)
            {
                /// return 0 as the standard deviation, so that we don't divide by 0 later
                return 0;
            }

            /// Iterate over all of the students in the list
            for (int i = 0; i < numOfStudents; i++)
            {
                /// Calculate the difference between each student's average and the class average
                /// Square that result and divide by the number of students on the list
                /// Add up this result for each of the students to compute the variance
                variance += Math.Pow(listOfStudents[i].Average() - classAverage, 2) / numOfStudents;
            }

            /// Return the square root of the variance to get standard deviation 
            return Math.Sqrt(variance);
        }

        /// <summary>
        /// Adds a new student to the list of students.
        /// </summary>
        /// <param name="name">Name of the new student</param>
        /// <param name="id">Student's ID number</param>
        public void AddStudent(string name, int id)
        {
            /// Add the new student to the list
            listOfStudents.Add(new Student(name, id));
        }
    }
}
